using System;
using System.Collections;
using System.ComponentModel;
using System.Web.UI.WebControls;
using Sedna.Core.Controller;
using Sedna.Core.Controller.Configurations;
using Sedna.Core.Controls.Support;
using Sedna.Core.Controls.Support.Javascript;
using Sedna.Core.DataBinding;
using Sedna.Core.Tiles.Contents;

namespace Sedna.Core.Controls
{

    public class Button : System.Web.UI.WebControls.Button, IContent, IConfigurationAware, ILabelledControl, IControlDataLoadAware, ICommandAware, IClientScriptingControl
	{
		private ICommandConfiguration configuration;
		private string configurationId = "configuration.default.Button";
		private string textKey;
        private string toolTipKey;
		
		private String contentPlaceHolderId;

		protected IDataBinder binder;
        private bool clientScriptingEnabled;
        private string clientVariable;
        private string nodeName;
        private string javascriptClass;

        public String ContentPlaceHolderId
		{
			get { return contentPlaceHolderId;}
			set { contentPlaceHolderId = value;}
		}

		public IConfiguration Configuration
		{
			get { return configuration; }
			set { this.configuration = (ICommandConfiguration)value; }
		}


		[Bindable(true), Category("Sedna"), DefaultValue("configuration.default.Button")]
		public string ConfigurationId
		{
			get { return configurationId; }
			set { this.configurationId = value; }
		}

		public string TextKey
		{
			get { return textKey; }
			set { textKey = value; }
		}

        public string ToolTipKey
        {
            get { return toolTipKey; }
            set { toolTipKey = value; }
        }

        public string LocalizedToolTip
        {
            get
            {
                if (Configuration.DataTranslator != null && Configuration.DataTranslator.GetType() != typeof(TrivialDataTranslator))
                {
                    return ToolTip;
                }
                return Configuration.GetLocalizedPostfixLabel(ToolTipKey, ToolTip);
            }
        }
        
        string ICommandAware.OnClick
		{
			get { return Attributes["onclick"]; }
			set { Attributes["onclick"]=value; }
		}

		public Button() :base()
		{
			this.CssClass = "btn";
		}

		public Button(IConfiguration configuration) : this()
		{
			this.Configuration = configuration;
			this.ConfigurationId = configuration.ObjectName;
//			this.ID=configuration.Id;
			BuildControlFromConfiguration();

		}

        private void BuildControlFromConfiguration()
        {
            this.ID = configuration.Id;
            IClientScriptingConfiguration clientScriptingConfiguration = Configuration as IClientScriptingConfiguration;
            if (clientScriptingConfiguration == null)
            {
                return;
            }

            ClientScriptingEnabled = clientScriptingConfiguration.ClientScriptingEnabled;
            ClientVariable = clientScriptingConfiguration.ClientVariable;
            ToolTip = Configuration.ToolTip;
            ToolTipKey = Configuration.ToolTipKey;
        }

        public Button(string id, string textKey, string text, IConfiguration configuration ):this(configuration)
		{
			this.ID = id;
			this.TextKey = textKey;
			this.Text = text;
            BuildControlFromConfiguration();
		}

		public Button(string id, string textKey, string text):this()
		{
			this.ID = id;
			this.TextKey = textKey;
			this.Text = text;
		}


		protected override void OnInit(EventArgs e)
		{
			if(configuration == null)
			{
				configuration = (ICommandConfiguration)SpringContextFactory.GetContext().GetObject(configurationId);
			}
			this.Click += new EventHandler(this.OnClick);
			Build();
			//Build();
			ControlUtil.SetupClientAttributes(this, configuration);
			binder=new DataBinder(this, configuration, ExecutionContext.GetCurrent(ClientID));
			base.OnInit (e);
		}


		protected void Build()
		{

			this.Visible = configuration.IsVisibleForPrincipal();
			this.Enabled = configuration.IsEnabledForPrincipal()&&configuration.Enabled;

			if(configuration.CssClass != null)
			{
				this.CssClass = configuration.CssClass;
			}


			if (this.ID==null&&configuration.Id!=null)
			{
				this.ID=configuration.Id;	
			}
			

			if(this.Text == null || this.Text == string.Empty)
			{
				this.Text = configuration.Label;
			}

			if(this.Width.IsEmpty)
			{
				this.Width=configuration.Width;
			}

			this.TextKey = configuration.TextKey;
	
	
			this.Text = configuration.GetLocalizedPostfixLabel(textKey, this.Text);
			this.CausesValidation = configuration.CausesValidation;
            this.ValidationGroup = configuration.ValidationGroup;

            this.CommandName = configuration.CommandName;
//            if (configuration.CommandArgumentGenerator != null)
//            {
//                this.CommandArgument = configuration.CommandArgumentGenerator.GenerateCommandArguments(configuration, ExecutionContext.GetCurrent(ClientID));
//            }
		}

		protected void OnClick(object sender, EventArgs e)
		{
			if (CausesValidation && !Page.IsValid)
			{
				return;
			}
			Button button = (Button)sender;
//			IActionExecutor actionExecutor = (IActionExecutor)SpringContextFactory.GetContext().GetObject("runtime.ActionExecutor");
			IExecutionContext executionContext = ExecutionContext.GetCurrent(ClientID);
			executionContext["infrastructure.commandName"] = button.configuration.CommandName;
			executionContext["infrastructure.commandArgument"] = button.CommandArgument;
			ControlUtil.ExecuteAction(executionContext, Context, Configuration, this.ClientID);
//			actionExecutor.ExecuteAction(Context, executionContext, configuration);
			RaiseBubbleEvent(this, new ModelUpdateEventArgs(executionContext));
		}

		protected override void OnLoad(EventArgs e)
		{
			base.OnLoad(e);
			IExecutionContext executionContext = ExecutionContext.GetCurrent(ClientID);
			Unbind();
			ControlUtil.ExecuteOnLoad(executionContext, Context, Configuration, this.ClientID);

            if (Configuration.VisibleBindPath != null)
                this.Visible = true; // To reach the OnPreRender method and analyze visibility in the Bind method
		}

		public void OnDataLoad()
		{
			IDictionary executionContext = ExecutionContext.GetCurrent(ClientID);
			ControlUtil.ExecuteOnDataLoad(executionContext, Context, Configuration, this.ClientID);
		}

		protected override void OnPreRender(EventArgs e)
		{
			base.OnPreRender(e);
			IExecutionContext executionContext = ExecutionContext.GetCurrent(ClientID);
			ControlUtil.ExecuteOnPreRender(executionContext,Context, Configuration, this.ClientID);
			Bind();
			this.Text = configuration.GetLocalizedPostfixLabel(textKey, this.Text);
            ToolTip = LocalizedToolTip;
            if (ClientScriptingEnabled)
            {
                EnableClientScripting();
            }
		}

		private void AssignJScriptCommand()
		{
		    if (configuration.OnClick !=null)
		    {
                Attributes.Add("onclick", String.Format(configuration.OnClick, configuration.CommandArgumentGenerator != null
                                                                                   ? configuration.CommandArgumentGenerator.GenerateCommandArguments(configuration, ExecutionContext.GetCurrent(ClientID))
                                                                                   : String.Empty));
                return;    
		    }
		    
		    
			if(configuration.JScriptCommandName != null)
			{
                if (configuration.CommandArgumentGenerator != null)
                {
                    Attributes.Add("onclick", configuration.JScriptCommandName + "('" + configuration.CommandArgumentGenerator.GenerateCommandArguments(configuration, ExecutionContext.GetCurrent(ClientID)) + "');");
                }
                else
                {
                    Attributes.Add("onclick", String.Format("{0}();", configuration.JScriptCommandName));
                }
			}		    
		}

		private void Bind()
		{
            this.Visible = this.configuration.Visible;

            binder.Bind(new string[] { "Text", "TextKey", "CausesValidation", "Enabled", "Visible", "ValidationGroup" });
			Enabled=Enabled&&configuration.IsEnabledForPrincipal();
			Visible=Visible&&configuration.IsVisibleForPrincipal();


            if (configuration.CommandArgumentGenerator != null)
            {
                this.CommandName = configuration.CommandName;
                this.CommandArgument = configuration.CommandArgumentGenerator.GenerateCommandArguments(configuration, ExecutionContext.GetCurrent(ClientID));
            }

            AssignJScriptCommand();		    
		}

		private void Unbind()
		{
			binder.Unbind(new string[]{"Text", "TextKey", "Enabled", "CausesValidation", "Visible", "ValidationGroup"});
		}


        public string JavascriptClass
        {
            get { return javascriptClass; }
            set { javascriptClass = value; }
        }

        public string NodeName
        {
            get { return nodeName; }
        }

        public string ClientVariable
        {
            get { return clientVariable; }
            set { clientVariable = value; }
        }

        public bool ClientScriptingEnabled
        {
            get { return clientScriptingEnabled; }
            set { clientScriptingEnabled = value; }
        }

        private void EnableClientScripting()
        {
            ControlUtil.EnsureIdAttribute(this);
            JavascriptController controller = JavascriptController.Current;

            controller.DeclareClass("Button");
            controller.DeclareObjectWithQuotedParams(ClientVariable, "Button", ClientID);
        }

	}
}
